package com.bjy.qa.service.manage.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjy.qa.dao.manage.RoleDao;
import com.bjy.qa.dao.manage.RoleRouteDao;
import com.bjy.qa.dao.manage.RouteDao;
import com.bjy.qa.entity.MyPage;
import com.bjy.qa.entity.ResponsePagingData;
import com.bjy.qa.entity.manage.Role;
import com.bjy.qa.entity.manage.RolePermissionDTO;
import com.bjy.qa.entity.manage.RoleRoute;
import com.bjy.qa.entity.manage.Route;
import com.bjy.qa.service.manage.IRoleRouteService;
import com.bjy.qa.service.manage.IRoleService;
import com.bjy.qa.util.security.CustomFilterInvocationSecurityMetadataSource;
import org.apache.commons.lang.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class RoleService extends ServiceImpl<RoleDao, Role> implements IRoleService {
    @Resource
    RouteDao routeDao;

    @Resource
    RoleDao roleDao;

    @Resource
    RoleRouteDao roleRouteDao;

    @Resource
    IRoleRouteService iRoleRouteService;

    @Cacheable(cacheNames = {"qap:roleService.getPermission"})
    @Override
    public Map<String, Object> getPermission() {
        List<Route> roleList = recursiveGetPermission(0L);

        Map<String, Object> retMap = new HashMap<>();
        retMap.put("routes", roleList);
        retMap.put("directives", CustomFilterInvocationSecurityMetadataSource.menuRoleList);

        return retMap;
    }

    /**
     * 递归 得到所有权限（Route 菜单 + Permission 按钮）
     * @param parentId 父级 ID
     * @return
     */
    private List<Route> recursiveGetPermission(Long parentId) {
        List<Route> roleList = routeDao.getPermission(parentId);
        for (Route route : roleList) {
            route.setChildren(recursiveGetPermission(route.getId()));
        }
        return roleList;
    }

    @Override
    public List<String> getRolePermission(Long roleId) {
        return routeDao.getRolePermission(roleId);
    }

    @CacheEvict(cacheNames = {"qap:roleService.getPermission", "qap:matcherUrlRole"}, allEntries = true)
    @Override
    public Boolean saveRolePermission(RolePermissionDTO rolePermission) {
        Long roleId = rolePermission.getRoleId();

        // 将 permissions 转为 RoleRoute 对象
        List<RoleRoute> roleRouteList = new ArrayList<>();
        for (String permission : rolePermission.getPermissions()) {
            String[] temp = permission.split("-");
            if (temp.length == 2) {
                RoleRoute rr = new RoleRoute();
                rr.setRoleId(roleId);
                rr.setRouteId(Long.parseLong(temp[1]));
                roleRouteList.add(rr);
            }
        }

        roleRouteDao.delete(new QueryWrapper<RoleRoute>().eq("role_id", roleId)); // 删除原有的角色的所有权限（Route 菜单 + Permission 按钮）
        iRoleRouteService.saveBatch(roleRouteList); // 批量插入新的角色的所有权限（Route 菜单 + Permission 按钮）

        CustomFilterInvocationSecurityMetadataSource.menuRoleList = null; // 清空菜单权限缓存
        return true;
    }

    @Override
    public ResponsePagingData list(MyPage<Role> myPage) {
        Page<Role> page = new Page(myPage.getPageNum(), myPage.getPageSize()); // 构造待查询 page 对象
        page.setOrders(myPage.getOrders()); // 设置排序字段

        // 构造待查询 QueryWrapper
        Role role = myPage.getQuery();
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        if (role != null) {
            if (StringUtils.isNotBlank(role.getName())) {
                queryWrapper.like("name", role.getName());
            }
        }

        page = roleDao.selectPage(page, queryWrapper); // 按分页查询

        myPage.setTotalRecords(page.getTotal()); // 设置返回总记录数

        return new ResponsePagingData(myPage, page.getRecords());
    }

    @Override
    public List<Role> listAll() {
        // 构造待查询 QueryWrapper
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("id");

        return roleDao.selectList(queryWrapper);
    }

    @Override
    public List<Role> listAllProjectRoles() {
        // 构造待查询 QueryWrapper
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne("id", 1);
        queryWrapper.orderByAsc("id");

        return roleDao.selectList(queryWrapper);
    }

    @Override
    public Object add(Role role) {
        roleDao.insert(role);
        return role;
    }

    @Override
    public int update(Role role) {
        // 更新数据需要清除 UpdatedTime 和 CreatedTime，否则不会自动更新修改时间
        role.setUpdatedAt(null);
        role.setCreatedAt(null);

        return roleDao.updateById(role);
    }

    @CacheEvict(cacheNames = "qap:roleService.getPermission", allEntries = true)
    @Override
    public int delete(Long id) {
        // TODO: 2023/7/28 这里后续要判断一下是否有用户使用了该角色
//        // 删除 project 前，先判断是不是有用户关联了此 project
//        QueryWrapper<UserCompanyProject> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("project_id", id);
//        if (userCompanyProjectDao.selectCount(queryWrapper) > 0) {
//            throw new MyException("删除错误。已经有用户关联到此项目，请先删除关联关系！");
//        }

        roleRouteDao.delete(new QueryWrapper<RoleRoute>().eq("role_id", id)); // 删除 角色对应路由信息

        return roleDao.deleteById(id);
    }
}
